package org.springframework.cloud.netflix.feign.support;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.netflix.feign.FeignContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractGenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RestController;
import feign.RequestTemplate;
import lombok.Data;
/**
* @author Spencer Gibb
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringEncoderTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
"spring.application.name=springencodertest", "spring.jmx.enabled=false" })
@DirtiesContext
public class SpringEncoderTests {
@Autowired
private FeignContext context;
@Autowired
@Qualifier("myHttpMessageConverter")
private HttpMessageConverter<?> myConverter;
@Test
public void testCustomHttpMessageConverter() {
SpringEncoder encoder = this.context.getInstance("foo", SpringEncoder.class);
assertThat(encoder, is(notNullValue()));
RequestTemplate request = new RequestTemplate();
encoder.encode("hi", MyType.class, request);
Collection<String> contentTypeHeader = request.headers().get("Content-Type");
assertThat("missing content type header", contentTypeHeader, is(notNullValue()));
assertThat("missing content type header", contentTypeHeader.isEmpty(), is(false));
String header = contentTypeHeader.iterator().next();
assertThat("content type header is wrong", header, is("application/mytype"));
assertThat("request charset is null", request.charset(), is(notNullValue()));
assertThat("request charset is wrong", request.charset(), is(Charset.forName("UTF-8")));
}
@Test
public void testBinaryData() {
SpringEncoder encoder = this.context.getInstance("foo", SpringEncoder.class);
assertThat(encoder, is(notNullValue()));
RequestTemplate request = new RequestTemplate();
encoder.encode("hi".getBytes(), null, request);
assertThat("request charset is not null", request.charset(), is(nullValue()));
}
class MediaTypeMatcher extends ArgumentMatcher<MediaType> {
private MediaType mediaType;
public MediaTypeMatcher(String type, String subtype) {
this.mediaType = new MediaType(type, subtype);
}
@Override
public boolean matches(Object argument) {
if (argument instanceof MediaType) {
MediaType other = (MediaType) argument;
return this.mediaType.equals(other);
}
return false;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("MediaTypeMatcher{");
sb.append("mediaType=").append(this.mediaType);
sb.append('}');
return sb.toString();
}
}
@Data
protected static class MyType {
private String value;
}
protected interface TestClient {
}
@Configuration
@EnableAutoConfiguration
@RestController
protected static class Application implements TestClient {
@Bean
HttpMessageConverter<?> myHttpMessageConverter() {
return new MyHttpMessageConverter();
}
private static class MyHttpMessageConverter
extends AbstractGenericHttpMessageConverter<Object> {
public MyHttpMessageConverter() {
super(new MediaType("application", "mytype"));
}
@Override
protected boolean supports(Class<?> clazz) {
return false;
}
@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return true;
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
if (clazz == String.class) {
return true;
}
return false;
}
@Override
protected void writeInternal(Object o, Type type,
HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
}
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
public Object read(Type type, Class<?> contextClass,
HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return null;
}
}
}
}